#include "AddDataGloveHandlerDialog.h"
#include "ui_AddDataGloveHandlerDialog.h"

#include <QFileDialog>
#include <QCheckBox>
#include <QMessageBox>
#include <set>

AddDataGloveHandlerDialog::AddDataGloveHandlerDialog(QWidget* parent, MMM::MotionList motions) :
    QDialog(parent),
    ui(new Ui::AddDataGloveHandlerDialog),
    motions(motions),
    currentMotion(nullptr),
    motionConverted(false)
{
    ui->setupUi(this);

    loadMotions();

    loadConfiguration(settings.value("datagloveconverter/configfilepath", "").toString().toStdString());
    loadData(settings.value("datagloveconverter/datafilepath", "").toString().toStdString());

    connect(ui->ChooseMotionGroupBox, SIGNAL(toggled(bool)), this, SLOT(chooseMotionToggled(bool)));
    connect(ui->DataButton, SIGNAL(clicked()), this, SLOT(loadData()));
    connect(ui->ConfigButton, SIGNAL(clicked()), this, SLOT(loadConfiguration()));
    connect(ui->ConvertButton, SIGNAL(clicked()), this, SLOT(convert()));
    connect(ui->CancelButton, SIGNAL(clicked()), this, SLOT(close()));
}

AddDataGloveHandlerDialog::~AddDataGloveHandlerDialog() {
    delete ui;
}

bool AddDataGloveHandlerDialog::convertMotion() {
    exec();
    return motionConverted;
}

void AddDataGloveHandlerDialog::loadMotions() {
    for (MMM::MotionPtr motion : motions) {
        ui->ChooseMotionComboBox->addItem(QString::fromStdString(motion->getName()));
    }
    setCurrentMotion(0);
}

void AddDataGloveHandlerDialog::setCurrentMotion(int index) {
    if (index >= 0 && motions.size() > static_cast<std::size_t>(index)) {
        currentMotion = motions[index];
    }
}

void AddDataGloveHandlerDialog::loadConfiguration() {
    std::string converterConfigFilePath = QFileDialog::getOpenFileName(this, tr("Load data glove converter configuration"), settings.value("datagloveconverter/configfilepath", "").toString(), tr("XML files (*.xml)")).toStdString();
    loadConfiguration(converterConfigFilePath);
}

void AddDataGloveHandlerDialog::loadConfiguration(const std::string &converterConfigFilePath) {
    if (!converterConfigFilePath.empty()) {
        try {
            converter = MMM::DataGloveConverterPtr(new MMM::DataGloveConverter(converterConfigFilePath));
        }
        catch (MMM::Exception::MMMException &e) {
            QMessageBox* msgBox = new QMessageBox(this);
            std::string error_message = "Could not load data glove configuration file from " + converterConfigFilePath + "! " + e.what();
            msgBox->setText(QString::fromStdString(error_message));
            MMM_ERROR << error_message << std::endl;
            msgBox->exec();
            return;
        }
        setConfigLabel(converterConfigFilePath);
        settings.setValue("datagloveconverter/configfilepath", QString::fromStdString(converterConfigFilePath));
        enableConvertButton();
    }
}

void AddDataGloveHandlerDialog::setConfigLabel(const std::string &filePath) {
    QString label = QString::fromStdString(MMM::XML::getFileName(filePath));
    ui->ConfigLabel->setText(label);
    ui->ConfigLabel->setToolTip(label);
}

void AddDataGloveHandlerDialog::loadData() {
    std::string converterDataFilePath = QFileDialog::getOpenFileName(this, tr("Load data glove data"), settings.value("datagloveconverter/datafilepath", "").toString()).toStdString();
    loadData(converterDataFilePath);
}

void AddDataGloveHandlerDialog::loadData(const std::string &converterDataFilePath) {
    if (!converterDataFilePath.empty()) {
        this->converterDataFilePath = converterDataFilePath;
        setDataLabel(converterDataFilePath);
        settings.setValue("datagloveconverter/datafilepath", QString::fromStdString(converterDataFilePath));
        enableConvertButton();
    }
}

void AddDataGloveHandlerDialog::setDataLabel(const std::string &filePath) {
    QString label = QString::fromStdString(MMM::XML::getFileName(filePath));
    ui->DataLabel->setText(label);
    ui->DataLabel->setToolTip(label);
}

void AddDataGloveHandlerDialog::enableConvertButton() {
    if (converter && !converterDataFilePath.empty()) ui->ConvertButton->setEnabled(true);
}

void AddDataGloveHandlerDialog::convert() {
    try {
        currentMotion->addSensor(converter->convert(converterDataFilePath), ui->TimestepDeltaSpinBox->value());
        motionConverted = true;
        this->close();
    }
    catch (MMM::Exception::MMMException &e) {
        QMessageBox* msgBox = new QMessageBox(this);
        std::string error_message = std::string("Could not convert data glove data! ") + e.what();
        msgBox->setText(QString::fromStdString(error_message));
        MMM_ERROR << error_message << std::endl;
        msgBox->exec();
    }
}
